// 把data中的数据 使用Object.defineProperty重新定义
import {arrayMethods} from "./array";

class Observer {
    constructor(value) {
        // vue如果数据的层次过多，需要递归去解析对象中的属性，依次增加set/get方法
        // 给每一个监控过的对象都增加一个__ob__属性
        Object.defineProperty(value,'__ob__',{
            enumerable:false,
            configurable:false,
            value:this
        })
        if(Array.isArray(value)){
            /**
             * 如果是数组，不会对索引进行观测，因为会导致性能问题
             * 如果数组里面放的是对象，再监控
             */
            // 原型链查找，会向上查找，先查找到重写的，没有重写会继续向上查找
            value.__proto__ = arrayMethods;
            this.observerArray(value)
        }else{
            // 对对象进行监控
            this.walk(value)
        }
    }
    observerArray(value){
        for(let i = 0; i< value.length;i++){
            observe(value[i])
        }
    }
    walk(data){
        let keys = Object.keys(data);
        keys.forEach((key) => {
            defineReactive(data,key,data[key]) // 定义响应式数据
        })
    }
}
function defineReactive(data,key,value) {
    observe(value)
    Object.defineProperty(data,key,{
        get() {
            return value
        },
        set(newV) {
            if(newV == value)return;
            observe(newV) // 继续劫持，因为更新的数据可能会是一个对象
            console.log("数据修改")
            value = newV;
        }
    })
}
export function observe(data) {
    let isObj = (typeof data === 'object' && data !== null);
    if(!isObj)return;
    return new Observer(data);
}
